﻿using Outcoder;
using Outcoder.Concurrency;
using Outcoder.InversionOfControl;
using Outcoder.InversionOfControl.Containers.SimpleContainer;
using Outcoder.LauncherModel.Launchers;
using Outcoder.Messaging;
using Outcoder.Services;
using Outcoder.Services.Implementation;
using Outcoder.UserOptionsModel;

using Xamarin.Forms;

namespace CalciumTemplateApp
{
	class Bootstrapper
	{
		bool runPerformed;

		internal void Run()
		{
			if (runPerformed)
			{
				return;
			}

			runPerformed = true;
			InitializeContainer();
		}

		/// <summary>
		/// Initializes the IoC container by registering type associations 
		/// and singleton instances.
		/// </summary>
		void InitializeContainer()
		{
			/* Simple container is the Calcium IoC container that works with Windows Phone. 
			 * It supports both inversion of control and dependency injection. 
			 * It can be accessed globally using the Dependency class. 
			 * The Dependency class leverages the Microsoft ServiceLocator, 
			 * allowing you to change the IoC container implementation. */
			SimpleContainer container = new SimpleContainer();
			container.InitializeContainer();

			/* The following are type associations applicable 
			 * to both build configurations. */

			ISettingsStore localStore = new LocalSettingsStore();
#if WP81
			SettingsService settingsService = new SettingsService(localStore, new RoamingSettingsStore());
#else
			SettingsService settingsService = new SettingsService(localStore);
#endif
#if DEBUG
			settingsService.RaiseExceptionsOnConversionErrors = true;
#endif
			Dependency.Register<ISettingsService>(settingsService);

			var dialogService
				= new DialogService
				{
					/* Lambdas are used to retrieve the default message service captions, 
					 * which allows the language to be changed at run-time. */
					//	DefaultMessageCaptionFunc = () => AppResources.DialogService_DefaultMessageCaption,
					//	DefaultQuestionCaptionFunc = () => AppResources.DialogService_DefaultQuestionCaption,
					//	DefaultWarningCaptionFunc = () => AppResources.DialogService_DefaultWarningCaption,
					//	DefaultErrorCaptionFunc = () => AppResources.DialogService_DefaultErrorCaption,
				};
			Dependency.Register<IDialogService>(dialogService);

			Dependency.Register<IProvider<ISynchronizationContext>, UIContextProvider>();
			Dependency.Register<IMessenger, Messenger>(true);
			Dependency.Register<IUserOptionsService, UserOptionsService>(true);
			Dependency.Register<IStringParserService, StringParserService>(true);

			AppSettings.Instance.Initialize();
			Dependency.Register(AppSettings.Instance);
			
			/* Build configuration specific associations. */
#if DEBUG
			RegisterDebugTypes();
#else
			RegisterReleaseTypes();
#endif
		}

		/// <summary>
		/// Registers the debug types. 
		/// Mock types are used for types that cause the app to be deactivated.
		/// </summary>
		void RegisterDebugTypes()
		{
			Dependency.Register<IMarketplaceService>(new MockMarketplaceService { Trial = true });
			Dependency.Register<IMarketplaceDetailTask>(new MockMarketplaceDetailTask());
		}

		/// <summary>
		/// Registers the release types. 
		/// Since the app will fail marketplace certification if the assembly 
		/// is built using a debug configuration, the release configuration 
		/// guarantees that no mock type registrations will make it into a published app.
		/// </summary>
		void RegisterReleaseTypes()
		{
			Dependency.Register<IMarketplaceService, MarketplaceService>();
#if WINDOWS_PHONE
			Dependency.Register<IMarketplaceDetailTask, MarketplaceDetailTaskAdapter>();
#endif
		}
	}
}
